/*!
 * maptalks.heatmap v0.6.1
 * LICENSE : MIT
 * (c) 2016-2019 maptalks.org
 */
/*!
 * requires maptalks@^0.25.0
 */
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('maptalks')) :
        typeof define === 'function' && define.amd ? define(['exports', 'maptalks'], factory) :
            (factory((global.maptalks = global.maptalks || {}),global.maptalks));
}(this, (function (exports,maptalks) { 'use strict';

    function createCommonjsModule(fn, module) {
        return module = { exports: {} }, fn(module, module.exports), module.exports;
    }

    var simpleheat_1 = createCommonjsModule(function (module) {
        'use strict';

        module.exports = simpleheat;

        function simpleheat(canvas) {
            if (!(this instanceof simpleheat)) return new simpleheat(canvas);

            this._canvas = canvas = typeof canvas === 'string' ? document.getElementById(canvas) : canvas;

            this._ctx = canvas.getContext('2d');
            this._width = canvas.width;
            this._height = canvas.height;

            this._max = 1;
            this._data = [];
        }

        simpleheat.prototype = {

            defaultRadius: 25,

            defaultGradient: {
                0.4: 'blue',
                0.6: 'cyan',
                0.7: 'lime',
                0.8: 'yellow',
                1.0: 'red'
            },

            data: function data(_data) {
                this._data = _data;
                return this;
            },

            max: function max(_max) {
                this._max = _max;
                return this;
            },

            add: function add(point) {
                this._data.push(point);
                return this;
            },

            clear: function clear() {
                this._data = [];
                return this;
            },

            radius: function radius(r, blur) {
                blur = blur === undefined ? 15 : blur;

                // create a grayscale blurred circle image that we'll use for drawing points
                var circle = this._circle = this._createCanvas(),
                    ctx = circle.getContext('2d'),
                    r2 = this._r = r + blur;

                circle.width = circle.height = r2 * 2;

                ctx.shadowOffsetX = ctx.shadowOffsetY = r2 * 2;
                ctx.shadowBlur = blur;
                ctx.shadowColor = 'black';

                ctx.beginPath();
                ctx.arc(-r2, -r2, r, 0, Math.PI * 2, true);
                ctx.closePath();
                ctx.fill();

                return this;
            },

            resize: function resize() {
                this._width = this._canvas.width;
                this._height = this._canvas.height;
            },

            gradient: function gradient(grad) {
                // create a 256x1 gradient that we'll use to turn a grayscale heatmap into a colored one
                var canvas = this._createCanvas(),
                    ctx = canvas.getContext('2d'),
                    gradient = ctx.createLinearGradient(0, 0, 0, 256);

                canvas.width = 1;
                canvas.height = 256;

                for (var i in grad) {
                    gradient.addColorStop(+i, grad[i]);
                }

                ctx.fillStyle = gradient;
                ctx.fillRect(0, 0, 1, 256);

                this._grad = ctx.getImageData(0, 0, 1, 256).data;

                return this;
            },

            draw: function draw(minOpacity) {
                if (!this._circle) this.radius(this.defaultRadius);
                if (!this._grad) this.gradient(this.defaultGradient);

                // updated by baidm at 2021/6/26,because row 136 errored
                if (!this._width || !this._height) return ;

                var ctx = this._ctx;

                ctx.clearRect(0, 0, this._width, this._height);

                // draw a grayscale heatmap by putting a blurred circle at each data point
                for (var i = 0, len = this._data.length, p; i < len; i++) {
                    p = this._data[i];
                    ctx.globalAlpha = Math.max(p[2] / this._max, minOpacity === undefined ? 0.05 : minOpacity);
                    ctx.drawImage(this._circle, p[0] - this._r, p[1] - this._r);
                }

                // colorize the heatmap, using opacity value of each pixel to get the right color from our gradient
                var colored = ctx.getImageData(0, 0, this._width, this._height);
                this._colorize(colored.data, this._grad);
                ctx.putImageData(colored, 0, 0);

                return this;
            },

            _colorize: function _colorize(pixels, gradient) {
                for (var i = 0, len = pixels.length, j; i < len; i += 4) {
                    j = pixels[i + 3] * 4; // get gradient color from opacity value

                    if (j) {
                        pixels[i] = gradient[j];
                        pixels[i + 1] = gradient[j + 1];
                        pixels[i + 2] = gradient[j + 2];
                    }
                }
            },

            _createCanvas: function _createCanvas() {
                if (typeof document !== 'undefined') {
                    return document.createElement('canvas');
                } else {
                    // create a new canvas instance in node.js
                    // the canvas class needs to have a default constructor without any parameter
                    return new this._canvas.constructor();
                }
            }
        };
    });

    function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }

    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

    function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

    function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); }

    var options = {
        'max': 1,
        'gradient': {
            0.4: 'blue',
            0.6: 'cyan',
            0.7: 'lime',
            0.8: 'yellow',
            1.0: 'red'
        },
        'radius': 25,
        'blur': 15,
        'heatValueScale': 1,
        'minOpacity': 0.05
    };

    var HeatLayer = function (_maptalks$Layer) {
        _inherits(HeatLayer, _maptalks$Layer);

        function HeatLayer(id, heats, options) {
            _classCallCheck(this, HeatLayer);

            if (!Array.isArray(heats)) {
                options = heats;
                heats = null;
            }

            var _this = _possibleConstructorReturn(this, _maptalks$Layer.call(this, id, options));

            _this._heats = heats || [];
            return _this;
        }

        HeatLayer.prototype.getData = function getData() {
            return this._heats;
        };

        HeatLayer.prototype.setData = function setData(heats) {
            this._heats = heats || [];
            return this.redraw();
        };

        HeatLayer.prototype.addPoint = function addPoint(heat) {
            if (!heat) {
                return this;
            }
            if (heat[0] && Array.isArray(heat[0])) {
                maptalks.Util.pushIn(this._heats, heat);
            } else {
                this._heats.push(heat);
            }
            return this.redraw();
        };

        HeatLayer.prototype.onConfig = function onConfig(conf) {
            for (var p in conf) {
                if (options[p]) {
                    return this.redraw();
                }
            }
            return this;
        };

        HeatLayer.prototype.redraw = function redraw() {
            var renderer$$1 = this._getRenderer();
            if (renderer$$1) {
                renderer$$1.clearHeatCache();
                renderer$$1.setToRedraw();
            }
            return this;
        };

        HeatLayer.prototype.isEmpty = function isEmpty() {
            if (!this._heats.length) {
                return true;
            }
            return false;
        };

        HeatLayer.prototype.clear = function clear() {
            this._heats = [];
            this.redraw();
            this.fire('clear');
            return this;
        };

        /**
         * Export the HeatLayer's JSON.
         * @return {Object} layer's JSON
         */


        HeatLayer.prototype.toJSON = function toJSON(options) {
            if (!options) {
                options = {};
            }
            var json = {
                'type': this.getJSONType(),
                'id': this.getId(),
                'options': this.config()
            };
            var data = this.getData();
            if (options['clipExtent']) {
                var clipExtent = new maptalks.Extent(options['clipExtent']);
                var r = this._getHeatRadius();
                if (r) {
                    clipExtent = clipExtent._expand(r);
                }
                var clipped = [];
                for (var i = 0, len = data.length; i < len; i++) {
                    if (clipExtent.contains(new maptalks.Coordinate(data[i][0], data[i][1]))) {
                        clipped.push(data[i]);
                    }
                }
                json['data'] = clipped;
            } else {
                json['data'] = data;
            }

            return json;
        };

        /**
         * Reproduce a HeatLayer from layer's JSON.
         * @param  {Object} json - layer's JSON
         * @return {maptalks.HeatLayer}
         * @static
         * @private
         * @function
         */


        HeatLayer.fromJSON = function fromJSON(json) {
            if (!json || json['type'] !== 'HeatLayer') {
                return null;
            }
            return new HeatLayer(json['id'], json['data'], json['options']);
        };

        HeatLayer.prototype._getHeatRadius = function _getHeatRadius() {
            if (!this._getRenderer()) {
                return null;
            }
            return this._getRenderer()._heatRadius;
        };

        return HeatLayer;
    }(maptalks.Layer);

    HeatLayer.mergeOptions(options);

    HeatLayer.registerJSONType('HeatLayer');

    HeatLayer.registerRenderer('canvas', function (_maptalks$renderer$Ca) {
        _inherits(_class, _maptalks$renderer$Ca);

        function _class() {
            _classCallCheck(this, _class);

            return _possibleConstructorReturn(this, _maptalks$renderer$Ca.apply(this, arguments));
        }

        _class.prototype.draw = function draw() {
            var map = this.getMap(),
                layer = this.layer,
                extent = map.getContainerExtent();
            var maskExtent = this.prepareCanvas(),
                displayExtent = extent;
            if (maskExtent) {
                maskExtent = maskExtent.convertTo(function (c) {
                    return map._pointToContainerPoint(c);
                });
                //out of layer mask
                if (!maskExtent.intersects(extent)) {
                    this.completeRender();
                    return;
                }
                displayExtent = extent.intersection(maskExtent);
            }

            if (!this._heater) {
                this._heater = simpleheat_1(this.canvas);
            }
            this._heater.radius(layer.options['radius'] || this._heater.defaultRadius, layer.options['blur']);
            if (layer.options['gradient']) {
                this._heater.gradient(layer.options['gradient']);
            }
            this._heater.max(layer.options['max']);
            //a cache of heat points' viewpoints.
            if (!this._heatViews) {
                this._heatViews = [];
            }

            var heats = layer.getData();
            if (heats.length === 0) {
                this.completeRender();
                return;
            }
            var data = this._heatData(heats, displayExtent);
            this._heater.data(data).draw(layer.options['minOpacity']);
            this.completeRender();
        };

        _class.prototype.drawOnInteracting = function drawOnInteracting() {
            this.draw();
        };

        _class.prototype._heatData = function _heatData(heats, displayExtent) {
            var map = this.getMap(),
                layer = this.layer;
            var projection = map.getProjection();
            var data = [],
                r = this._heater._r,
                max = layer.options['max'] === undefined ? 1 : layer.options['max'],
                cellSize = r / 2,
                grid = [],
                panePos = map.offsetPlatform(),
                offsetX = panePos.x % cellSize,
                offsetY = panePos.y % cellSize;
            var heat = void 0,
                p = void 0,
                cell = void 0,
                x = void 0,
                y = void 0,
                k = void 0;
            displayExtent = displayExtent.expand(r).convertTo(function (c) {
                return new maptalks.Point(map._containerPointToPrj(c));
            });
            this._heatRadius = r;
            for (var i = 0, l = heats.length; i < l; i++) {
                heat = heats[i];
                if (!this._heatViews[i]) {
                    this._heatViews[i] = projection.project(new maptalks.Coordinate(heat[0], heat[1]));
                }
                p = this._heatViews[i];
                if (displayExtent.contains(p)) {
                    p = map._prjToContainerPoint(p);
                    x = Math.floor((p.x - offsetX) / cellSize) + 2;
                    y = Math.floor((p.y - offsetY) / cellSize) + 2;

                    k = (heat[2] !== undefined ? +heat[2] : 0.1) * layer.options['heatValueScale'];

                    grid[y] = grid[y] || [];
                    cell = grid[y][x];

                    if (!cell) {
                        grid[y][x] = [p.x, p.y, k];
                    } else {
                        cell[0] = (cell[0] * cell[2] + p.x * k) / (cell[2] + k); // x
                        cell[1] = (cell[1] * cell[2] + p.y * k) / (cell[2] + k); // y
                        cell[2] += k; // cumulated intensity value
                    }
                }
            }
            for (var _i = 0, _l = grid.length; _i < _l; _i++) {
                if (grid[_i]) {
                    for (var j = 0, ll = grid[_i].length; j < ll; j++) {
                        cell = grid[_i][j];
                        if (cell) {
                            data.push([Math.round(cell[0]), Math.round(cell[1]), Math.min(cell[2], max)]);
                        }
                    }
                }
            }
            return data;
        };

        _class.prototype.onZoomEnd = function onZoomEnd() {
            delete this._heatViews;
            _maptalks$renderer$Ca.prototype.onZoomEnd.apply(this, arguments);
        };

        _class.prototype.onResize = function onResize() {
            _maptalks$renderer$Ca.prototype.onResize.apply(this, arguments);
            if (this.canvas) {
                this._heater._width = this.canvas.width;
                this._heater._height = this.canvas.height;
            }
        };

        _class.prototype.onRemove = function onRemove() {
            this.clearHeatCache();
            delete this._heater;
        };

        _class.prototype.clearHeatCache = function clearHeatCache() {
            delete this._heatViews;
        };

        return _class;
    }(maptalks.renderer.CanvasRenderer));

    exports.HeatLayer = HeatLayer;

    Object.defineProperty(exports, '__esModule', { value: true });

    typeof console !== 'undefined' && console.log('maptalks.heatmap v0.6.1 changed by baidm, requires maptalks@^0.25.0.');

})));